﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace LcfContols
{
    public class DatePanel : Control
    {
        #region 事件
        /// <summary>
        /// 时间改变事件
        /// </summary>
        public event Action<ulong, ulong> timeChange;

        #endregion

        #region 变量
        /// <summary>
        /// 开始时间
        /// </summary>
        private ulong starttime;
        /// <summary>
        /// 结束时间
        /// </summary>
        private ulong endtime;
        #endregion

        #region 子控件
        /// <summary>
        /// 不限
        /// </summary>
        RadioButton allrbt = new RadioButton();
        /// <summary>
        /// 今天
        /// </summary>
        RadioButton todayrbt = new RadioButton();
        /// <summary>
        /// 昨天
        /// </summary>
        RadioButton yesrbt = new RadioButton();
        /// <summary>
        /// 本月
        /// </summary>
        RadioButton tomonth = new RadioButton();
        /// <summary>
        /// 指定
        /// </summary>
        RadioButton checkrbt = new RadioButton();
        /// <summary>
        /// 开始时间
        /// </summary>
        DateTimePicker startpicker = new DateTimePicker();
        /// <summary>
        /// 结束时间
        /// </summary>
        DateTimePicker endpicker = new DateTimePicker();
        /// <summary>
        /// 加载按钮
        /// </summary>
        Button load = new Button();
        #endregion

        #region 属性
        /// <summary>
        /// 开始时间戳
        /// </summary>
        public ulong StartTime
        {
            get
            {
                return starttime;
            }
        }

        /// <summary>
        /// 开始时间戳
        /// </summary>
        public DateTime STime
        {
            get
            {
                return LongToTime((long)starttime);
            }
        }

        /// <summary>
        /// 结束时间戳
        /// </summary>
        public ulong EndTime
        {
            get
            {
                return endtime;
            }
        }

        /// <summary>
        /// 结束时间戳
        /// </summary>
        public DateTime ETime
        {
            get
            {
                return LongToTime((long)endtime);
            }
        }

        /// <summary>
        /// 是否显示加载按钮
        /// </summary>
        public bool ButtomShow
        {
            get { return load.Visible; }
            set { load.Visible = value; }
        }

        #endregion

        public DatePanel()
        {
            Size s = TextSize("不限");
            allrbt.Text = "不限";
            allrbt.Width = s.Width+40;
            todayrbt.Text = "今天";
            todayrbt.Width = s.Width + 40;
            yesrbt.Text = "昨天";
            yesrbt.Width = s.Width + 40;
            tomonth.Text = "本月";
            tomonth.Width = s.Width + 40;
            checkrbt.Text = "指定";
            checkrbt.Width = s.Width + 30;
            load.Text = "加载";
            Controls.AddRange(new Control[] { allrbt,todayrbt,yesrbt,tomonth,checkrbt,startpicker,endpicker,load});
            allrbt.CheckedChanged += CheckedChanged;
            todayrbt.CheckedChanged += CheckedChanged;
            yesrbt.CheckedChanged += CheckedChanged;
            tomonth.CheckedChanged += CheckedChanged;
            checkrbt.CheckedChanged += CheckedChanged;
            load.Click += Load_Click;
            allrbt.Checked = true;
            #region 开始时间不能大于结束时间，结束时间不能小于开始时间
            endpicker.MinDate = startpicker.Value;
            startpicker.MaxDate = endpicker.Value;
            startpicker.ValueChanged += Startpicker_ValueChanged;
            endpicker.ValueChanged += Endpicker_ValueChanged;
            #endregion
        }

        #region 确保时间范围有效

        private void Endpicker_ValueChanged(object sender, EventArgs e)
        {
            startpicker.MaxDate = endpicker.Value;
        }

        private void Startpicker_ValueChanged(object sender, EventArgs e)
        {
            endpicker.MinDate = startpicker.Value;
        }

        #endregion

        #region 选择时间设置
        /// <summary>
        /// 开始时间选择器
        /// </summary>
        private DateTimePicker startTime
        {
            get
            {
                return startpicker;
            }
        }

        /// <summary>
        /// 结束时间选择器
        /// </summary>
        private DateTimePicker endTime
        {
            get
            {
                return endpicker;
            }
        }
        #endregion

        /// <summary>
        /// 时间戳转换成时间
        /// </summary>
        /// <param name="timeStamp">时间戳</param>
        /// <returns></returns>
        public static DateTime LongToTime(long timeStamp)
        {
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            long lTime = timeStamp * 10000000;
            TimeSpan toNow = new TimeSpan(lTime);
            return dtStart.Add(toNow);
        }

        /// <summary>
        /// 加载按钮触发
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Load_Click(object sender, EventArgs e)
        {
            ChangeTime();
            if (timeChange != null)
                timeChange(starttime, endtime);
        }

        /// <summary>
        /// 选择框变化
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CheckedChanged(object sender, EventArgs e)
        {
            RadioButton r = sender as RadioButton;
            if (r.Checked){
                ChangeTime();
                if(timeChange != null)
                    timeChange(starttime, endtime);
            }
        }

        /// <summary>
        /// 文字大小
        /// </summary>
        /// <returns></returns>
        private Size TextSize(string str)
        {
            return TextRenderer.MeasureText(str, Font);
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            int left = 10;
            Local(allrbt,ref left);
            Local(todayrbt, ref left);
            Local(yesrbt, ref left);
            Local(tomonth, ref left);
            Local(checkrbt, ref left);
            Local(startpicker, ref left);
            using (Brush pen = new SolidBrush(ForeColor)){
                Size s = TextSize("--");
                e.Graphics.DrawString("--", Font, pen, new Point(left+5,(Height-s.Height)/2));
                left +=s.Width+5;
            }
            Local(endpicker, ref left);
            left += 10;
            load.Height = TextSize(load.Text).Height + 10;
            Local(load, ref left);
            base.OnPaint(e);
        }

        /// <summary>
        /// Y轴位置
        /// </summary>
        /// <param name="con"></param>
        /// <returns></returns>
        private void Local(Control con,ref int left)
        {
            con.Location = new Point(left, (Height - con.Height) / 2);
            left += con.Width ;
        }

        /// <summary>
        /// 重新检测时间
        /// </summary>
        private void ChangeTime()
        {
            if(todayrbt.Checked)
            {
                starttime = DayTimeStamp();
                endtime = DayTimeStamp(1);
            }else if (yesrbt.Checked)
            {
                starttime = DayTimeStamp(-1);
                endtime = DayTimeStamp();
            }else if(tomonth.Checked)
            {
                starttime = MonthTimeStamp();
                endtime = MonthTimeStamp(1);
            }else if (checkrbt.Checked)
            {
                starttime = GetTimeStamp(startpicker.Value.Date);
                endtime = GetTimeStamp(endpicker.Value.Date);
            }
            else
            {
                starttime = 0;
                endtime = DayTimeStamp(2);
            }
        }

        /// <summary>
        /// 触发时间更新时间
        /// </summary>
        /// <param name="starttime"></param>
        /// <param name="endtime"></param>
        public void Reload(){
            ChangeTime();
            if (timeChange != null)
                timeChange(starttime, endtime);
        }

        /// <summary>
        /// 返回时间戳
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static ulong GetTimeStamp(DateTime time)
        {
            return Convert.ToUInt64((time.ToUniversalTime().Ticks - 621355968000000000) / 10000000);
        }
        
        /// <summary>
        /// 时间戳转为C#格式时间
        /// </summary>
        /// <param name="timeStamp">Unix时间戳格式</param>
        /// <returns>C#格式时间</returns>
        public static DateTime GetTime(long timeStamp)
        {
            DateTime dtStart = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            long lTime = timeStamp * 10000000;
            TimeSpan toNow = new TimeSpan(lTime);
            return dtStart.Add(toNow);
        }

        /// <summary>
        /// 几天之前或几天之后0点时间戳
        /// </summary>
        /// <returns></returns>
        public static ulong DayTimeStamp(int days = 0)
        {
            DateTime today = new DateTime(DateTime.Now.Year, DateTime.Now.Month, DateTime.Now.Day);
            return GetTimeStamp(today.AddDays(days));
        }

        /// <summary>
        /// 修改选择内容
        /// </summary>
        /// <param name="check"></param>
        public void ChangeChecked(Checked check)
        {
            switch (check)
            {
                case Checked.All:
                    allrbt.Checked = true;
                    break;
                case Checked.Appoint:
                    checkrbt.Checked = true;
                    break;
                case Checked.Today:
                    todayrbt.Checked = true;
                    break;
                case Checked.Yesterday:
                    yesrbt.Checked = true;
                    break;
                case Checked.ThisMonth:
                    tomonth.Checked = true;
                    break;
            }
        }

        /// <summary>
        /// 获取几个月前或几个月后1号0点时间戳
        /// </summary>
        /// <param name="months"></param>
        /// <returns></returns>
        public static ulong MonthTimeStamp(int months = 0)
        {
            DateTime m = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
            return GetTimeStamp(m.AddMonths(months));
        }

        /// <summary>
        /// 选择框类型
        /// </summary>
        public enum Checked
        {
            /// <summary>
            /// 不限
            /// </summary>
            All,
            /// <summary>
            /// 今天
            /// </summary>
            Today,
            /// <summary>
            /// 昨天
            /// </summary>
            Yesterday,
            /// <summary>
            /// 本月
            /// </summary>
            ThisMonth,
            /// <summary>
            /// 指定
            /// </summary>
            Appoint
        }

    }
}
